package conf

import (
	"gitee.com/zylvcxq/gotham-utils/env"
	"gitee.com/zylvcxq/gotham-utils/event"
	"github.com/go-kratos/kratos/contrib/registry/etcd/v2"
	"github.com/prometheus/client_golang/prometheus"
	clientv3 "go.etcd.io/etcd/client/v3"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

/*
   @author:zhongyang
   @date:2023/5/25
   @description:相关配置
*/

var EventServer event.Publisher

var GServer GothamServer

var (
	MetricSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Namespace: "server",
		Subsystem: "requests",
		Name:      "duration_sec",
		Help:      "server requests duratio(sec).",
		Buckets:   []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.250, 0.5, 1},
	}, []string{"kind", "operation"})

	MetricRequests = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "client",
		Subsystem: "requests",
		Name:      "code_total",
		Help:      "The total number of processed requests",
	}, []string{"kind", "operation", "code", "reason"})
)

type GothamServer struct {
	Application `json:"application"`
}

type Application struct {
	Server *Server `json:"server"`
	Data   *Data   `json:"data"`
}

func InitZapLogger() (zapLogger *zap.Logger) {
	mode := env.GetMode()
	if mode == "dev" {
		zapLogger, _ = zap.NewDevelopment()
		zapLogger = zapLogger.Sugar().Desugar()
	} else {
		// 生产环境配置
		config := zap.NewProductionConfig()
		config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder

		// 创建文件输出
		fileOutput, err := os.OpenFile("log/gotham-plan-manage.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			panic(err)
		}

		// 创建自定义 WriteSyncer，将日志同时输出到控制台和文件
		writeSyncer := zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(fileOutput))

		// 创建核心 logger
		core := zapcore.NewCore(zapcore.NewJSONEncoder(config.EncoderConfig), writeSyncer, config.Level)
		zapLogger = zap.New(core)
	}
	return zapLogger
}

// InitEtcdRegister 向ETCD注册服务
func InitEtcdRegister() *etcd.Registry {
	// new etcd client
	client, err := clientv3.New(clientv3.Config{
		Endpoints: []string{env.GetETCDUrl()},
	})
	if err != nil {
		panic(err)
	}
	// new reg with etcd client
	reg := etcd.New(client)
	return reg
}

// InitTrace 注册全局链路追踪
func InitTrace() error {
	// 创建 Jaeger exporter
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(env.GetJaegerUrl())))
	if err != nil {
		return err
	}
	tp := tracesdk.NewTracerProvider(
		// 将基于父span的采样率设置为100%
		tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(1.0))),
		// 始终确保在生产中批量处理
		tracesdk.WithBatcher(exp),
		// 在资源中记录有关此应用程序的信息
		tracesdk.WithResource(resource.NewSchemaless(
			semconv.ServiceNameKey.String("gotham-plan-manage"),
			attribute.String("exporter", "jaeger"),
			attribute.Float64("float", 312.23),
		)),
	)
	otel.SetTracerProvider(tp)
	return nil
}

func NewRabbitMQPublisher() error {
	server, err := event.NewRabbitMQServer()
	if err != nil {
		return err
	}
	EventServer = server
	return nil
}
